
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>

#include "evalsoc.h"
#include "evalsoc_uart.h"
#include "dbg_cli.h"

#include "arp.h"
#include "udp.h"
#include "ethqos.h"




#if 0

static inline uint32_t bits_set( uint32_t org, uint32_t mask )
{
	return 0;
}

#endif



uint16_t htons(uint16_t hostshort) {
    // 检查当前系统是否为大端字节序
    uint16_t test = 0x00FF;
    if (*(uint8_t*)&test == 0xFF) {
        // 小端字节序，需要转换
        return (hostshort >> 8) | ((hostshort & 0xFF) << 8);   
    } else {
        // 大端字节序，不需要转换
        return hostshort;
    }
}



/*
空闲 packet 构成单链表.
FIFO 结构.
每个节点 0x680 字节, 1664 字节.
*/


typedef struct _tag_fpa_entry {
	struct _tag_fpa_entry * next;
} fpa_entry_t;


static fpa_entry_t * fhead = NULL;
static fpa_entry_t * ftail = NULL;


int fpa_alloc( void ** pptr )
{
	fpa_entry_t * pent;
	
	// 如果头指针为空，返回错误码 1234
	if ( fhead == NULL )  {
	return 1234;
	}
	
	/* 从头节点取下一个节点. */
	pent = fhead;
	fhead = fhead->next;
	if ( fhead == NULL )  {
	// 如果头指针变为空，说明链表中只有一个节点，将尾指针也置空
	ftail = NULL;
	}
	
	*pptr = (void *)pent;
	// 分配成功，返回 0
	return 0;
 
}


int fpa_free( void * ptr )
{
	fpa_entry_t * pent;

	pent = (fpa_entry_t *)ptr;
	pent->next = NULL;


	if ( ftail != NULL )  {
		
		ftail->next = pent;
		ftail = pent;

	} else {

		/* 特殊情况, 链表为空.. */
		ftail = pent;
		fhead = pent;
	}

	return 0;
}


/*
packet block , [sadr, cnt] 全部放到 list 中管理.
描述符内存 数量固定, 不需要在此处管理.
*/
void eqos_fpa_init( uintptr_t sadr, int cnt )
{
	uintptr_t bufptr = sadr;

	for ( int i=0; i<cnt; i++ )  {

		fpa_free( (void *)bufptr );
		bufptr += 0x680;
	}

	//
	printf( "fpa init, cnt=%d, end ptr, %x\n", cnt, bufptr );
	return;
}



int mdio_read( dw_eth_mac_regs_t * pmac, uint8_t phyadr, uint8_t regadr, uint16_t * pval )
{
	uint32_t temp;

	// 1100: CSR clock/12, GOC = 2'b11 (write)
	temp = ((uint32_t)phyadr << 5) | regadr;
	temp = ( temp << 8) | 0xC;
	temp = ( temp << 6) | 0x3;
	temp = temp << 2;

	//
	pmac->MDIO_Addr = temp;
	pmac->MDIO_Addr = temp | 0x1;

	// wait for complete
	while ( true )  {

		temp = pmac->MDIO_Addr;
		if ( (temp & 0x1) == 0 )  {
			break;
		}

	}

	//
	temp = pmac->MDIO_Data;
	*pval = (uint16_t)temp;
	return 0;
}


int mdio_write( dw_eth_mac_regs_t * pmac, uint8_t phyadr, uint8_t regadr, uint16_t tval )
{
	uint32_t temp;

	// 16 bits data.
	pmac->MDIO_Data = (uint32_t)tval;

	// 1100: CSR clock/12, GOC = 2'b01 (write)
	temp = ((uint32_t)phyadr << 5) | regadr;
	temp = ( temp << 8) | 0xC;
	temp = ( temp << 6) | 0x1;
	temp = temp << 2;

	//
	pmac->MDIO_Addr = temp;
	pmac->MDIO_Addr = temp | 0x1;

	// wait for complete
	while ( true )  {
		temp = pmac->MDIO_Addr;
		if ( (temp & 0x1) == 0 )  {
			break;
		}
	}

	//
	return 0;
}



int dbg_eth_mdio( void * parg, int argc, const char * argv[] )
{
	int iret;
	dw_eth_mac_regs_t * pmac = (dw_eth_mac_regs_t *)ETHER_QOS_BASE;
	uint32_t temp;
	uint8_t phyadr;
	uint8_t regadr;
	uint16_t value;


	if ( argc < 2 )  {
		goto usage;
	}

	if ( 0 == strcmp( argv[1], "scan") )  {

		for ( phyadr=0; phyadr<32; phyadr++ )  {
			mdio_read( pmac, phyadr, 2, &value );
			if ( (value != 0) && (value != 0xFFFF )  )  {
				break;
			}
		}

		if ( phyadr >= 32 )  {
			printf( "all scan fail..\n" );
			return 1;
		}

		// 
		printf( " phyaddr = %u\n", phyadr );
		printf( "ident[0] = %04X\n", value );
		
		mdio_read( pmac, phyadr, 3, &value );
		printf( "ident[1] = %04X\n", value );
		return 0;
	
	} else if ( 0 == strcmp( argv[1], "read" )  )  {
		
		if ( argc < 4 )  {
			goto usage;
		}

		// phy addr
		iret = debug_str2uint( argv[2], &temp );
		if ( iret != 0 )  {
			printf( "phy addr fail, %d", iret );
			goto usage;
		}

		phyadr = (uint8_t)temp;

		// reg addr
		iret = debug_str2uint( argv[3], &temp );
		if ( iret != 0 )  {
			printf( "reg addr fail, %d\n", iret );
			goto usage;
		}

		regadr = (uint8_t)temp;
		iret = mdio_read( pmac, phyadr, regadr, &value );
		if ( iret != 0 )  {
			printf( "read fail, %d\n", iret );
			return 2;
		}

		printf( "%04X\n", value );
		return 0;

	} else if ( 0 == strcmp( argv[1], "write" )  )  {
		
		if ( argc < 5 )  {
			goto usage;
		}

		// phy addr
		iret = debug_str2uint( argv[2], &temp );
		if ( iret != 0 )  {
			printf( "phy addr parse fail, %d", iret );
			goto usage;
		}

		phyadr = (uint8_t)temp;

		// reg addr
		iret = debug_str2uint( argv[3], &temp );
		if ( iret != 0 )  {
			printf( "reg addr parse fail, %d\n", iret );
			goto usage;
		}

		regadr = (uint8_t)temp;

		// value 
		iret = debug_str2uint( argv[4], &temp );
		if ( iret != 0 )  {
			printf( "value parse fail, %d\n", iret );
			goto usage;
		}

		value = (uint16_t)temp;

		iret = mdio_write( pmac, phyadr, regadr, value );
		if ( iret != 0 )  {
			printf( "write fail, %d\n", iret );
			return 3;
		}
		return 0;
	}


usage:
	printf( "usage:\n" );
	printf( "\t%s  scan\n", argv[0] );
	printf( "\t%s  read <phy> <reg>\n", argv[0] );
	printf( "\t%s write <phy> <reg> <val>\n", argv[0] );
	return 0;
}


/*
预设前提条件.
phyid = 7
: status.
: soft reset.
: kmb <0/1> : 禁止 1000M 能力.
*/
int dbg_eth_phy( void * parg, int argc, const char * argv[] )
{
	int iret;
	uint32_t temp;
	dw_eth_mac_regs_t * pmac = (dw_eth_mac_regs_t *)ETHER_QOS_BASE;
	uint8_t phyadr = 7;
	uint16_t reg1;
	uint16_t reg17;

	if ( argc < 2 )  {
		goto usage;
	}

	if ( 0 == strcmp( argv[1], "status") )  {

		/**/
		mdio_read( pmac, phyadr, 1, &reg1 );
		mdio_read( pmac, phyadr, 17, &reg17 );

		printf( "reg[ 1] = %x\n", reg1 );
		printf( "reg[17] = %x\n", reg17 );

		// reg1[5] : 1 = Auto-Negotiation process complete.
		if ( 0 == (reg1 & 0x20) )  {
			printf( "Auto-Negotiation complete = 0\n" );
		} else {
			printf( "Auto-Negotiation complete = 1\n" );
		}

		// reg17[10] : Link (real time)
		printf( "%u : Link (real time)\n", (reg17 >> 10) & 0x1 );
		printf( "%u : Speed\n", (reg17 >> 14) & 0x3 );
		printf( "%u : Duplex\n", (reg17 >> 13) & 0x1 );
		return 0;

	} else if ( 0 == strcmp( argv[1], "aneg") )  {

		if ( argc < 3 )  {
			goto usage;
		}

		//
		iret = debug_str2uint( argv[2], &temp );
		if ( iret != 0 )  {
			printf( "aneg parse fail %d\n", iret );
			goto usage;
		}

		if ( temp == 0 )  {

			// reg9[9:8] : 1000BASE-T, Full-Duplex, Half-Duplex
			mdio_read( pmac, phyadr, 9, &reg1 );
			reg1 = reg1 & 0xFCFF;
			mdio_write( pmac, phyadr, 9, reg1 );

			// reg4[8:7] : 100BASE-TX, Full-Duplex, Half-Duplex
			mdio_read( pmac, phyadr, 4, &reg17 );
			reg17 = reg17 & 0xFE7F;
			mdio_write( pmac, phyadr, 4, reg17 );

		} else if ( temp == 1 )  {

			// reg9[9:8] : 1000BASE-T, Full-Duplex, Half-Duplex
			mdio_read( pmac, phyadr, 9, &reg1 );
			reg1 = reg1 & 0xFCFF;
			mdio_write( pmac, phyadr, 9, reg1 );

			// reg4[8:7] : 100BASE-TX, Full-Duplex, Half-Duplex
			mdio_read( pmac, phyadr, 4, &reg17 );
			reg17 = reg17 | 0x180;
			mdio_write( pmac, phyadr, 4, reg17 );

		} else if ( temp == 2 )  {

			// reg9[9:8] : 1000BASE-T, Full-Duplex, Half-Duplex
			mdio_read( pmac, phyadr, 9, &reg1 );
			reg1 = reg1 | 0x300;
			mdio_write( pmac, phyadr, 9, reg1 );

			// reg4[8:7] : 100BASE-TX, Full-Duplex, Half-Duplex
			mdio_read( pmac, phyadr, 4, &reg17 );
			reg17 = reg17 | 0x180;
			mdio_write( pmac, phyadr, 4, reg17 );

		} else {
			printf( "aneg range fail, 0/1/2\n" );
			goto usage;			
		}

		return 0;
	
	} else if ( 0 == strcmp( argv[1], "delay") )  {

		if ( argc < 3 )  {
			goto usage;
		}

		//
		iret = debug_str2uint( argv[2], &temp );
		if ( iret != 0 )  {
			printf( "kmb parse fail %d\n", iret );
			goto usage;
		}

		if ( temp != 0 ) {
			temp = 0x82;
		}

		// rgmii delay 
		mdio_read( pmac, phyadr, 20, &reg17 );
		reg17 = reg17 & 0xFF0D;
		reg17 = reg17 | (uint16_t)temp | 0x50;
		mdio_write( pmac, phyadr, 20, reg17 );
		return 0;
		
	} else if ( 0 == strcmp( argv[1], "reset") )  {

		// soft reset.
		mdio_read( pmac, phyadr, 0, &reg1 );
		reg1 = reg1 | 0x8000;
		mdio_write( pmac, phyadr, 0, reg1 );
		return 0;
	}

	
usage:
	printf( "usage:\n" );
	printf( "\t%s  status\n", argv[0] );
	printf( "\t%s  aneg  <0/1/2>\n", argv[0] );
	printf( "\t%s  delay <0/1>\n", argv[0] );
	printf( "\t%s  reset\n", argv[0] );	
	return 0;
}

static void eqos_delay( uint32_t ticks )
{
    for ( uint32_t i=0; i<ticks; i++ )  {
        asm volatile ( "nop" );
    }
}





typedef struct  {
	uint32_t des0;
	uint32_t des1;
	uint32_t des2;
	uint32_t des3;
} eqos_tx_desc;


void eqos_tx_desc_init( eqos_tx_desc * ptxdc, void * dataptr )
{
	ptxdc->des0 = (uint32_t)(uintptr_t)dataptr;
	ptxdc->des1 = 0;
	ptxdc->des2 = 0;
	ptxdc->des3 = 0;
}


typedef struct  {
	uint32_t des0;
	uint32_t des1;
	uint32_t des2;
	uint32_t des3;
} eqos_rx_desc;



/*
数据 buffer 固定长度 1792 (0x700)
*/
void eqos_rx_desc_init( eqos_rx_desc * prxdc, void * dataptr )
{
	prxdc->des0 = (uint32_t)(uintptr_t)dataptr;
	prxdc->des1 = 0;
	prxdc->des2 = 0;

	// OWN = 1, IOC=1, BUF1V=1
	prxdc->des3 = 0xC1000000;
}



static int eqos_dma_init( eqos_context_t * pctx, dw_eth_dma_regs_t * pdma )
{
	int iret;
	void * pblk;
	uint32_t temp;
	eqos_rx_desc * prxdc;
	eqos_tx_desc * ptxdc;

	// 
	temp = pdma->Mode;
	pdma->Mode = temp | 0x1;
	eqos_delay( 100 );

	// check 
	while ( true )  {
		temp = pdma->Mode;
		if ( (temp & 0x1) == 0 )  {
			break;
		}
	}

	// pdma->SysBus_Mode

	// descriptor list
	// 0x90000 : SRAM, 64K bytes.
	prxdc = (eqos_rx_desc *)(uintptr_t)0x90000;
	pctx->rxdesc_idx = 0;
	for ( int i=0; i<16; i++ )  {
		
		iret = fpa_alloc( &pblk );
		if ( iret != 0 )  {
			return __LINE__;
		}

		pctx->rxblk_ary[i] = pblk;
		eqos_rx_desc_init( &prxdc[i], pblk );
	}

	// recvs ring regs.
	pdma->Chan[0].RxDesc_List_Address = (uintptr_t)prxdc;
	pdma->Chan[0].RxDesc_Tail_Pointer = (uintptr_t)&prxdc[15];
	pdma->Chan[0].RxDesc_Ring_Length = 15;


	// trans desc init
	ptxdc = (eqos_tx_desc *)(uintptr_t)0x90800;
	pctx->txdesc_idx = 0;
	pctx->txing_idx = 0;
	for ( int i=0; i<16; i++ )  {
		eqos_tx_desc_init( &ptxdc[i], NULL );
	}

	// trans ring regs.
	pdma->Chan[0].TxDesc_List_Address = (uintptr_t)ptxdc;
	// TX tail pointer not written until we need to TX a packet
	// pdma->Chan[0].TxDesc_Tail_Pointer = (uintptr_t)ptxdc;
	pdma->Chan[0].TxDesc_Ring_Length = 15;

	//
	pdma->Chan[0].Interrupt_Enable = 0;
	pdma->Chan[0].Control = 0;
	pdma->Chan[0].Rx_Control = (0x700 << 1) | 1;
	pdma->Chan[0].Tx_Control = 1;
	return 0;
}



static int eqos_mtl_init( dw_eth_mtl_regs_t * pmtl )
{
	pmtl->Operation_Mode = 0;
	pmtl->Queue[0].Tx_Operation_Mode = 2;		// TSF = 1
	pmtl->Queue[0].Rx_Operation_Mode = 0x20;		// RSF = 1

	return 0;
}


static int eqos_mac_init( dw_eth_mac_regs_t * pmac )
{
	pmac->Mac_Addr_High = 0x00E0;
	pmac->Mac_Addr_Low = 0xFC332211;

	pmac->Packet_Filter = 0x80000001;
	pmac->Int_Enable = 0;
	return 0;
}



void eqos_tx_desc_tosend( eqos_tx_desc * ptxdc, void * dataptr, int tlen )
{
	uint32_t temp;

	ptxdc->des0 = (uint32_t)(uintptr_t)dataptr;
	ptxdc->des1 = 0;

	// IOC = 1, Interrupt on Completion 
	ptxdc->des2 = 0x80000000 | (uint32_t)tlen;
	__WMB();

	temp = (uint32_t)tlen;
	temp = temp | 0xB0000000;
	ptxdc->des3 = temp;
	return;
}




/*
检查输入 packet header 信息.
我们仅仅测试 ipv4 packet.
如果检查通过,  交换 src_ip 和 dst_ip .

返回值, 表示返回给 PC 的内容长度.
<=0 表示报文不符合, 需要丢弃.
*/
int check_edit_packet(eqos_context_t * pctx, uint8_t * pdat, int tlen )
{

	// check tlen
	if ( tlen < 64 )  {
		return -1;
	}

	//check mac address
	if ( (pdat[6] != 0x84) || (pdat[7] != 0x47) || (pdat[8] != 0x09) || (pdat[9] != 0x37) || (pdat[10] != 0xd6) || (pdat[11] != 0xaa) )  {
		return -1;
	}
	//udp destination ip and protocol
	if(  pdat[30] == 0xa9 && pdat[31] == 0xfe && pdat[32] == 0xce &&  pdat[33] == 0xc8  &&  pdat[23] == 0x11)
	{
		//udp
		udp_make_reply(pctx,pdat,tlen);
		//打印udp数据包
		debug_dump_hex( (uint8_t *)pdat, tlen );
		return 1;
	}
	//check ip address
	if((pdat[38] != DEV_IP[0])||(pdat[39] != DEV_IP[1])||(pdat[40] != DEV_IP[2])||(pdat[41] != DEV_IP[3]) )
	{
		return -1;
	}

	// eth type : 0x0800, IPV4.
    // eth type : 0x0806, ARP.
	if ( (pdat[12] == 0x08) && (pdat[13] == 0x06))  {

		//arp
		arp_make_reply(pctx,pdat,tlen);
		//打印arp数据包
		debug_dump_hex( (uint8_t *)pdat,tlen );

		return 2;
	}
	else if ( (pdat[12] == 0x08) && (pdat[13] == 0x00 ))  {
		// ipv4
		// swap src_ip and dst_ip
	
		return -1;
	}else{

		return -1;
	}
}



/*
构造一个简单 packet,  启动 tx dma,  让 MAC 发送出去.
*/
/**
 * @brief 发送数据包
 * @param pctx  上下文
 * @param pdat  数据包
 * @param tlen  数据包长度
 * @return 0 成功, 其他失败
 */
int dbg_eth_trans( eqos_context_t * pctx, void * pdat, int tlen )
{
	dw_eth_dma_regs_t * pdma = (dw_eth_dma_regs_t *)( ETHER_QOS_BASE + 0x1000 );
	eqos_tx_desc * ptxdc;
	int txidx;

	
	/* get next desc */
	ptxdc = (eqos_tx_desc *)(uintptr_t)0x90800;
	txidx = pctx->txdesc_idx;

	/* 检查 OWN */
	if ( ptxdc[txidx].des3 & 0x80000000 )  {
		printf( "tx fail, OWN=1. \n");
		fpa_free( pdat );
		return 123;
	}

	/* desc OWN and ControlBits */
	eqos_tx_desc_tosend( &ptxdc[txidx], pdat, tlen);
	__RWMB();

	/* write tail pointer, tx resume */
	pdma->Chan[0].TxDesc_Tail_Pointer = (uintptr_t)&ptxdc[txidx];

	/**/
	pctx->txblk_ary[txidx] = pdat;
	txidx += 1;
	txidx &= 0xF;
	pctx->txdesc_idx = txidx;
	return 0;
}


/*
回收 packet block.
*/
static void eqos_dma_comp_trans( eqos_context_t * pctx, dw_eth_dma_regs_t * pdma )
{
	int txidx;
	eqos_tx_desc * ptxdc;

	/**/
	ptxdc = (eqos_tx_desc *)(uintptr_t)0x90800;
	txidx = pctx->txing_idx;

	while ( txidx != pctx->txdesc_idx )  {

		//
		if ( ptxdc[txidx].des3 & 0x80000000 )  {
			break;
		}

		// 回收...
		fpa_free( pctx->txblk_ary[txidx] );

		// next...
		txidx +=1;
		txidx &=0xF;
	}

	pctx->txing_idx = txidx;
	return;
}



static void eqos_dma_try_recv( eqos_context_t * pctx, dw_eth_dma_regs_t * pdma )
{
	int iret;
	void * pblk;
	void * cpkt;
	eqos_rx_desc * prxdc;
	int rxidx;
	uint32_t temp;
	uint32_t tlen;
	//uint32_t errs;

	prxdc = (eqos_rx_desc *)(uintptr_t)0x90000;
	rxidx = pctx->rxdesc_idx;

	while ( true )  {

		temp = prxdc[rxidx].des3;
		if ( (temp & 0x80000000) != 0 )  {
			break;;
			}

			// 
		cpkt = pctx->rxblk_ary[rxidx];

			// init desc
		iret = fpa_alloc( &pblk );
		if ( iret == 0 )  {
			
			eqos_rx_desc_init( &prxdc[rxidx], pblk );
			pctx->rxblk_ary[rxidx] = pblk;

			// write tail pointer
			pdma->Chan[0].RxDesc_Tail_Pointer = (uintptr_t)&prxdc[rxidx];
				
			rxidx += 1;
			rxidx &= 0xF;

		} else {

			// error....
			printf( "recv, alloc fail\n" );
			break;;
		}

		// proc packet, print flag.
		tlen = temp & 0x7FFF;
		temp = temp >> 15;
		//errs = (temp >> 4) & 0x3f;
		//printf( "[%d], flag=%lx, errs=%lx, len=%lu\n", rxidx, temp, errs, tlen );


		/* 检查 packet . */
		iret = check_edit_packet( pctx,(uint8_t *)cpkt, tlen );
		//printf("iret = %d\n",iret);

		switch (iret) {
			case -1:
				fpa_free(cpkt);
				break;
			case 1:
				// udp
				printf("---------udp-------\n");
				break;
			case 2:
				// arp
				printf("---------arp-------\n");
				break;
			default:
				printf("---------other-------\n");
				break;
		}
		


		// print payload.
		//debug_dump_hex( (uint8_t *)cpkt, 64 );
		// fpa_free( cpkt );

		// send cpkt .
		// dbg_eth_trans( pctx, cpkt, (int)tlen );

		fpa_free( cpkt );
	}	

	/**/
	pctx->rxdesc_idx = rxidx;
	return;
}



int dbg_eth_mac( void * parg, int argc, const char * argv[] )
{
	dw_eth_mac_regs_t * pmac = (dw_eth_mac_regs_t *)ETHER_QOS_BASE;
	dw_eth_mtl_regs_t * pmtl = (dw_eth_mtl_regs_t *)( ETHER_QOS_BASE + 0xC00 );
	dw_eth_dma_regs_t * pdma = (dw_eth_dma_regs_t *)( ETHER_QOS_BASE + 0x1000 );
	int iret;
	uint32_t speed;
	uint32_t temp;
	eqos_context_t eqctx;

	if ( argc < 2 )  {
		printf( "speed args need\n" );
		return 0;
	}
	
	iret = debug_str2uint( argv[1], &speed );
	if ( iret != 0 )  {
		printf( "speed parse fail, %d\n", iret );
		return 0;
	}

	if ( (speed != 10) && (speed != 100) && (speed != 1000) )  {
		printf( "speed range fail, %lu\n", speed );
		return 0;
	}


	// fpa init.
	eqos_fpa_init( 0x91000, 36 );

	// dma init
	eqos_dma_init( &eqctx, pdma );

	// mtl init
	eqos_mtl_init( pmtl );

	// mac init
	eqos_mac_init( pmac );

	// mac speed, txclk freq
	temp = pmac->Config;
	temp = temp & 0xFFFF0FFF;

	if ( speed == 1000 )  {
		temp = temp | 0x2000;			// 1000M, Full-duplex
	} else if ( speed == 100 )  {
		temp = temp | 0xE000;			// 100M, Full-duplex
	} else   {
		temp = temp | 0xA000;			// 10M, Full-duplex
	}
	
	pmac->Config = temp;
	pmac->Config = temp | 3;

	printf( "init succ....\n" );

	// check recv..
	while ( true )  {

		// check dma, chan[0], status
		temp = pdma->Chan[0].Status;
		if ( temp & 0xFFF3000 )  {
			// error flag..
			printf( "bus errs : %lx\n", temp );
			break;
		}


		if ( temp & 0x40 )  {

			// Receive Interrupt.
			pdma->Chan[0].Status = 0x40;

			// try proc recv
			eqos_dma_try_recv( &eqctx, pdma );
			
		} else if ( temp & 0x1 )  {

			// Transmit Interrupt, 
			pdma->Chan[0].Status = 0x1;

			// 回收资源.
			eqos_dma_comp_trans( &eqctx, pdma );

		} else  {
			
			int iret;

			// 
			iret = uart_try_getch( UART2 );
			if ( iret == 3 )  {
				
				//arp_make_request( &eqctx, (uint8_t *)"169.254.206.164");
				printf( "arp request\n" );
				/* ctrl + c */
				printf( "status : %lx\n", temp );
				printf( "tx idx : %d, %d\n", eqctx.txdesc_idx, eqctx.txing_idx );
			}
			
		}

	}

	return 0;
}


int dbg_eth_check( void * parg, int argc, const char * argv[] )
{
	dw_eth_dma_regs_t * pdma = (dw_eth_dma_regs_t *)( ETHER_QOS_BASE + 0x1000 );
	uint32_t ints;
	uint32_t dbgs;

	//
	ints = pdma->Int_Status;
	dbgs = pdma->Dbg_Status;

	//
	printf( "ints = %lX\n", ints );
	printf( "dbgs = %lX\n", dbgs );
	return 0;
}

